using System;
using System.Text;
using System.Threading;
using System.Collections;
using System.Collections.Generic;


namespace Foundations.Net.Pooling
{
    public delegate T ConstructorDelegate<T>() where T : class;
    public delegate void ActivationDelegate<T>(T Object) where T : class;
    public delegate void DeActivationDelegate<T>(T Object) where T : class;

    public static class PoolManager
    {
        private static ReaderWriterLock _lck;
        private static Dictionary<Type,Object> _pools;

        static PoolManager()
        {
            _lck = new ReaderWriterLock();
            _pools = new Dictionary<Type, Object>();
        }

        /// <summary>
        /// 
        /// </summary>
        /// <typeparam name="T">Type of object that will be stored in the pool.</typeparam>
        /// <param name="Capacity">Size of the pool, the value cannot exceed 64.</param>
        /// <returns></returns>
        public static bool CreatePool<T>(Int32 Capacity) where T : class
        {
            return CreatePool<T>(Capacity, Timeout.Infinite, new ConstructorDelegate<T>(Construct<T>), new ActivationDelegate<T>(Activate<T>), new DeActivationDelegate<T>(DeActivate<T>));
        }

        /// <summary>
        /// 
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="Capacity"></param>
        /// <param name="TimeOut"></param>
        /// <returns></returns>
        public static bool CreatePool<T>(Int32 Capacity, Int32 TimeOut) where T : class
        {
            return CreatePool<T>(Capacity, TimeOut, new ConstructorDelegate<T>(Construct<T>), new ActivationDelegate<T>(Activate<T>), new DeActivationDelegate<T>(DeActivate<T>));
        }

        public static bool CreatePool<T>(Int32 Capacity, ConstructorDelegate<T> Construct) where T : class
        {
            return CreatePool<T>(Capacity, Timeout.Infinite, Construct, new ActivationDelegate<T>(Activate<T>), new DeActivationDelegate<T>(DeActivate<T>));
        }

        public static bool CreatePool<T>(Int32 Capacity, Int32 TimeOut, ConstructorDelegate<T> Construct) where T : class
        {
            return CreatePool<T>(Capacity, TimeOut, Construct, new ActivationDelegate<T>(Activate<T>), new DeActivationDelegate<T>(DeActivate<T>));
        }

        public static bool CreatePool<T>(Int32 Capacity, ActivationDelegate<T> Activate) where T : class
        {
            return CreatePool<T>(Capacity, Timeout.Infinite, new ConstructorDelegate<T>(Construct<T>), Activate, new DeActivationDelegate<T>(DeActivate<T>));
        }

        public static bool CreatePool<T>(Int32 Capacity, Int32 TimeOut, ActivationDelegate<T> Activate) where T : class
        {
            return CreatePool<T>(Capacity, TimeOut, new ConstructorDelegate<T>(Construct<T>), Activate, new DeActivationDelegate<T>(DeActivate<T>));
        }

        public static bool CreatePool<T>(Int32 Capacity, DeActivationDelegate<T> DeActivate) where T : class
        {
            return CreatePool<T>(Capacity, Timeout.Infinite, new ConstructorDelegate<T>(Construct<T>), new ActivationDelegate<T>(Activate<T>), DeActivate);
        }

        public static bool CreatePool<T>(Int32 Capacity, Int32 TimeOut, DeActivationDelegate<T> DeActivate) where T : class
        {
            return CreatePool<T>(Capacity, TimeOut, new ConstructorDelegate<T>(Construct<T>), new ActivationDelegate<T>(Activate<T>), DeActivate);
        }

        public static bool CreatePool<T>(Int32 Capacity, ActivationDelegate<T> Activate, DeActivationDelegate<T> DeActivate) where T : class
        {
            return CreatePool<T>(Capacity, Timeout.Infinite, new ConstructorDelegate<T>(Construct<T>), Activate, DeActivate);
        }

        public static bool CreatePool<T>(Int32 Capacity, Int32 TimeOut, ActivationDelegate<T> Activate, DeActivationDelegate<T> DeActivate) where T : class
        {
            return CreatePool<T>(Capacity, TimeOut, new ConstructorDelegate<T>(Construct<T>), Activate, DeActivate);
        }

        public static bool CreatePool<T>(Int32 Capacity, ConstructorDelegate<T> Construct, ActivationDelegate<T> Activate) where T : class
        {
            return CreatePool<T>(Capacity, Timeout.Infinite, Construct, Activate, new DeActivationDelegate<T>(DeActivate<T>));
        }

        public static bool CreatePool<T>(Int32 Capacity, Int32 TimeOut, ConstructorDelegate<T> Construct, ActivationDelegate<T> Activate) where T : class
        {
            return CreatePool<T>(Capacity, TimeOut, Construct, Activate, new DeActivationDelegate<T>(DeActivate<T>));
        }

        public static bool CreatePool<T>(Int32 Capacity, ConstructorDelegate<T> Construct, DeActivationDelegate<T> DeActivate) where T : class
        {
            return CreatePool<T>(Capacity, Timeout.Infinite, Construct, new ActivationDelegate<T>(Activate<T>), DeActivate);
        }

        public static bool CreatePool<T>(Int32 Capacity, Int32 TimeOut, ConstructorDelegate<T> Construct, DeActivationDelegate<T> DeActivate) where T : class
        {
            return CreatePool<T>(Capacity, TimeOut, Construct, new ActivationDelegate<T>(Activate<T>), DeActivate);
        }

        public static bool CreatePool<T>(Int32 Capacity, ConstructorDelegate<T> Construct, ActivationDelegate<T> Activate, DeActivationDelegate<T> DeActivate) where T : class
        {
            return CreatePool<T>(Capacity, Timeout.Infinite, Construct, Activate, DeActivate);
        }

        public static bool CreatePool<T>(Int32 Capacity, Int32 TimeOut, ConstructorDelegate<T> Construct, ActivationDelegate<T> Activate, DeActivationDelegate<T> DeActivate) where T : class
        { 
            try
            {
               ObjectPool<T> pool = null;  
               _lck.AcquireWriterLock(Timeout.Infinite);
               {
                    if (!_pools.ContainsKey(typeof(T)))
                    {
                       pool = new ObjectPool<T>(Capacity, TimeOut);
                        _pools.Add(typeof(T), pool);
                    }
                }

                if (pool != null)
                {
                    pool.Init(Construct, Activate, DeActivate);
                }
                return true;
            }
            catch
            {
                throw;
            }
            finally
            {
                _lck.ReleaseWriterLock();
            }
        }

        public static PooledObject<T> Get<T>() where T: class 
        {
            ObjectPool<T> pool;
             _lck.AcquireReaderLock(Timeout.Infinite);
            {
                try
                {
                    pool = (ObjectPool<T>)_pools[typeof(T)];
                }
                catch
                {
                    throw;
                }
                finally
                {
                    _lck.ReleaseReaderLock();
                }
                
            }

            return pool.Get();
        }

        static T Construct<T>()
        {
            return (T)Activator.CreateInstance(typeof(T));
        }

        static void Activate<T>(T Instance)
        {
            
        }

        static void DeActivate<T>(T Instance)
        {
            
        }


    }
}
